package com.hatic.money;

import java.util.List;
import java.util.Map;

import org.jxstar.dao.DaoParam;
import org.jxstar.dao.DmDao;
import org.jxstar.service.BusinessObject;
import org.jxstar.util.DateUtil;
import org.jxstar.util.factory.FactoryUtil;

/**
 * 生成投资计划结转记录，实现方法：
 * 取投资计划表的所有字段信息，复制一条新记录，状态修改为未提交、拟稿中，当年投资金额为剩余投资金额；
 * 申报年度为当前年度、申报日期为当前日期
 * 注意所有项目执行过程中反馈信息都依据项目ID与投资计划状态判断，避免反馈到已结转的投资计划中。
 * 
 * 结转计划中的金额值都在业务执行过程中反馈：
 * 预计总投资 -- 每个环节都反馈，可以手工修改；
 * 截止当前累计完成投资 -- 每次提交付款计划时都反馈，同时也要反馈到计划包中；
 * 上年度截止结转月份累计支付 -- 每次提交付款计划时都反馈，同时也要反馈到计划包中；
 * 上年度预计完成投资	 -- 这个值需要手工填写；
 * 上年度剩余月份预计支付 -- 自动计算值 = 上年度预计完成投资 - 上年度截止结转月份累计支付
 * 累计完成投资 -- 自动计算值 = 截止当前累计完成投资 + 上年度剩余月份预计支付
 * 本年度计划投资 -- 自动计算值 = 预计总投资 - 累计完成投资，可以手工修改
 * 
 * 被结转的原计划状态修改为“已结转”，不再执行，后期所有的金额反馈信息都反馈到新的结转计划中。
 *
 * @author TonyTan
 * @version 1.0, 2011-10-2
 */
public class PlanTranBO extends BusinessObject {
	private static final long serialVersionUID = 1L;
	
	//结转提交时判断如果新增了子计划，则修改当前计划为大计划,计划对应的项目，项目包状态改为大项目
	public String preTranAudit(String[] planIds) {
		for (int i = 0; i < planIds.length; i++) {
			updateBaoType(planIds[i]);
			updateProjBaoType(planIds[i]);
		}
		
		return _returnSuccess;
	}
	
	private boolean updateBaoType(String planId) {
		String sql = "update money_plan set bao_type = '2' where plan_id = ? and " +
		 			 "(select count(*) from money_plan where bao_type = '7' and plan_parentid = ?) > 0";

		DaoParam param = _dao.createParam(sql);
		param.addStringValue(planId);
		param.addStringValue(planId);
		
		return _dao.update(param);
	}
	
	private boolean updateProjBaoType(String planId) {
		String sql = "update project_base set bao_type = '2',projbao_type = '2' where plan_id = ? and " +
		 			 "(select count(*) from money_plan where bao_type = '7' and plan_parentid = ?) > 0";

		DaoParam param = _dao.createParam(sql);
		param.addStringValue(planId);
		param.addStringValue(planId);
		
		return _dao.update(param);
	}
	
	/**
	 * 删除新增的结转计划
	 * @param planIds
	 * @return
	 */
	public String preDelete(String[] planIds) {
		for (int i = 0; i < planIds.length; i++) {
			String planId = planIds[i];
			String oldParentId = getOldPlanId(planId);
			
			deleteSubPlan(planId, oldParentId);
			updateStatus(oldParentId);
		}
		
		return _returnSuccess;
	}
	
	/**
	 * 批量结转生成新的投资计划
	 * 
	 * @param planIds -- 选择的投资计划ID
	 * @return
	 */
	public String planTran(String[] planIds) {
		for (int i = 0; i < planIds.length; i++) {
			String planId = planIds[i];
			//取原投资计划
			Map<String,String> planData = DmDao.queryMap("money_plan", planId);
			
			//包类型有：0 普通计划、1 虚拟包、2 大计划，如果是虚拟包与大计划，则需要创建其子计划的结转计划
			String baoType = planData.get("bao_type");
			
			//先创建选择的计划的结转记录
			String newPlanId = createTranPlan(planId, planData);
			
			//如果是虚拟包，则再创建包下的所有子计划
			if (baoType.equals("1") ||  baoType.equals("2")) {
				createSubTranPlan(planId, newPlanId);
			}
		}
		return _returnSuccess;
	}
	
	/**
	 * 创建父计划下的所有子计划包，不含被中止的计划
	 * @param planId -- 父计划ID
	 * @param newPlanId -- 新的父计划ID
	 * @return
	 */
	private boolean createSubTranPlan(String planId, String newPlanId) {
		String sql = "select * from money_plan where plan_parentid = ? " +
				"and plan_status < '91'";
		DaoParam param = _dao.createParam(sql);
		param.addStringValue(planId);
		
		List<Map<String,String>> subplan = _dao.query(param);
		for (int i = 0, n = subplan.size(); i < n; i++) {
			Map<String,String> data = subplan.get(i);
			String planid = data.get("plan_id");
			
			//修改父计划ID
			data.put("plan_parentid", newPlanId);
			
			createTranPlan(planid, data);
		}
		
		return true;
	}
	
	/**
	 * 生成单个投资计划的子计划
	 * @param planId -- 计划ID
	 * @param planData -- 计划数据
	 * @return
	 */
	private String createTranPlan(String planId, Map<String,String> planData) {
		
		//计算新的申报年度
		int year = Integer.parseInt(planData.get("plan_year")) + 1;
		//取投资计划完成情况中的“下年计划付款”作为当年计划付款
		String year_money1 = planData.get("year_money1");
		if (year_money1.length() == 0) year_money1 = "0";
		
		//如果是在“结转投资计划公司上报”功能选择公司的投资计划结转，则状态为13待上报，根据部门ID判断
		String mystatus = "11";
		String deptId = planData.get("dept_id");
		if (deptId.substring(0, 4).equals("1001")) {
			mystatus = "13";
		}
		
		Map<String,String> repData = FactoryUtil.newMap();
		repData.put("auditing", "0");
		repData.put("audit_up", "0");
		repData.put("audit_sq", "0");
		repData.put("plan_status", mystatus);
		repData.put("plan_year", Integer.toString(year));
		//repData.put("plan_date", DateUtil.getToday());//申报日期不变
		repData.put("tran_date", DateUtil.getToday());
		repData.put("year_money", year_money1);
		repData.put("is_turn", "1");
		repData.put("oldplan_id", planData.get("plan_id"));
		repData.put("oldplan_status", planData.get("plan_status"));//在结转计划下达时用，根据该值判断是待实施，还是实施中
		repData.put("plan_parentid", planData.get("plan_parentid"));
		
		//处理计划管理状态，如果计划状态为“实施中”，则为续建20，否则为新开工30
		String projectStatus = "30";
		String planStatus = planData.get("plan_status");
		if (planStatus.equals("42")) {
			projectStatus = "20";
		}
		repData.put("plan_status2", projectStatus);
		
		String newPlanId = DmDao.copy("money_plan", planId, repData);
		
		//原计划状态修改为“结转中”
		updatePlanStatus(planId);
		
		return newPlanId;
	}
	
	//更新计划状态为“已结转”
	private boolean updatePlanStatus(String planId) {
		String usql = "update money_plan set oldplan_status = plan_status, plan_status = '72' where plan_id = ?";
		DaoParam param = _dao.createParam(usql);
		param.addStringValue(planId);
		return _dao.update(param);
	}
	
	//删除结转记录时，要删除其子计划，同时回滚子计划的状态
	private boolean deleteSubPlan(String parentId, String oldParentId) {
		//删除新增的子计划
		deleteSub(parentId);
		
		//恢复原子计划的状态
		updateSubStatus(oldParentId);
		
		return true;
	}
	
	//恢复原计划的状态
	private boolean updateStatus(String planId) {
		String usql = "update money_plan set plan_status = oldplan_status, oldplan_status = '' " +
				"where plan_id = ? ";
		DaoParam param = _dao.createParam(usql);
		param.addStringValue(planId);
		return _dao.update(param);
	}
	
	//恢复原子计划的状态
	private boolean updateSubStatus(String parentId) {
		String usql = "update money_plan set plan_status = oldplan_status, oldplan_status = '' " +
				"where plan_parentid = ? and plan_status < '91'";
		DaoParam param = _dao.createParam(usql);
		param.addStringValue(parentId);
		return _dao.update(param);
	}
	
	//删除新生成的子计划
	private boolean deleteSub(String parentId) {
		String sql = "delete from money_plan where plan_parentid = ?";
		DaoParam param = _dao.createParam(sql);
		param.addStringValue(parentId);
		return _dao.update(param);
	}
	
	//取投资计划的原计划ID
	private String getOldPlanId(String planId) {
		String sql = "select oldplan_id from money_plan where plan_id = ?";
		DaoParam param = _dao.createParam(sql);
		param.addStringValue(planId);
		
		Map<String, String> mpData = _dao.queryMap(param);
		return mpData.get("oldplan_id");
	}
}
